package algo3.algothief.controlador;

import java.io.IOException;
import java.util.HashMap;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import algo3.algothief.excepcion.CasoNoIniciadoException;
import algo3.algothief.modelo.Juego;
import algo3.algothief.vista.VistaJuego;

import org.xml.sax.SAXException;

public class ControladorJuego {

	private ControladorInicioDelJuego controladorDelInicioDelJuego;
	private ControladorFinalDelJuego controladorDelFinalDelJuego;
	
	private ControladorViaje controladorDelViaje;
	private ControladorVisita controladorDeLaVisita;
	private ControladorEmisionDeOrden controladorDeLaOrdenDeArresto;
	private ControladorPartida controladorDeLaPartida;
	
	private BufferedReader entradaDeTeclado;
	
	private Juego juego;
	
	private VistaJuego vistaDelJuego;
	
	private HashMap<String, String> opcionesDelJuego;
	
//---------------------------------------------------------------------------------------------------------

	public ControladorJuego(Juego juegoActual, VistaJuego vista) {
		InputStreamReader input = new InputStreamReader(System.in);
		this.entradaDeTeclado = new BufferedReader(input);
		
		this.controladorDelInicioDelJuego = new ControladorInicioDelJuego(juegoActual, vista);
		this.controladorDelFinalDelJuego = new ControladorFinalDelJuego(juegoActual, vista, controladorDelInicioDelJuego);
		
		this.juego = juegoActual;
		
		this.vistaDelJuego = vista;
		
		this.opcionesDelJuego = this.crearOpcionesDelJuego();
	}
	
//---------------------------------------------------------------------------------------------------------
	
	private void inicializarControladoresParaElNuevoCaso() throws CasoNoIniciadoException {
		this.controladorDelViaje = new ControladorViaje(juego, vistaDelJuego);
		this.controladorDeLaVisita = new ControladorVisita(juego, vistaDelJuego);
		this.controladorDeLaOrdenDeArresto = new ControladorEmisionDeOrden(juego, vistaDelJuego);
		this.controladorDeLaPartida = new ControladorPartida(juego, vistaDelJuego);
	}
	
	private HashMap<String, String> crearOpcionesDelJuego() {
		HashMap<String, String> opciones = new HashMap<String, String>();
		
		opciones.put(Integer.toString(1), "Viajar a un pais");
		opciones.put(Integer.toString(2), "Visitar un lugar de este pais");
		opciones.put(Integer.toString(3), "Emitir una orden de arresto contra alguien");
		opciones.put(Integer.toString(4), "Guardar la partida actual");
		opciones.put(Integer.toString(5), "Cargar una partida guardada");
			
		return opciones;
	}
	
	private String procesarAccionAElegir() throws IOException, CasoNoIniciadoException{
		String entrada = entradaDeTeclado.readLine();
		
		while (!opcionesDelJuego.containsKey(entrada)) {
			VistaJuego.graficarMensajeDeOpcionElegidaIncorrecta(entradaDeTeclado);
			
			vistaDelJuego.graficarMenuDeAccionesEnElJuego(opcionesDelJuego);
			entrada = entradaDeTeclado.readLine();
		}
			
		return opcionesDelJuego.get(entrada);
	}
	
//---------------------------------------------------------------------------------------------------------
	
	public void procesarEntradasDelJugador() throws ParserConfigurationException, SAXException, IOException, TransformerException {
		try {
			controladorDelInicioDelJuego.procesarEntradasInicialesDelJugador(entradaDeTeclado);
		
			while( controladorDelFinalDelJuego.seEligioSeguirJugando() ) {
				this.inicializarControladoresParaElNuevoCaso();
			
				while( juego.sePuedeSeguirJugando() ) {
					vistaDelJuego.graficarMenuDeAccionesEnElJuego(opcionesDelJuego);
					String eleccion = this.procesarAccionAElegir();
				
					if (eleccion.matches("Viajar a un pais")) 
						controladorDelViaje.procesarEntradasParaViajar(entradaDeTeclado);
				
					else if(eleccion.matches("Visitar un lugar de este pais")) 
						controladorDeLaVisita.procesarEntradasParaVisitar(entradaDeTeclado);
				
					else if(eleccion.matches("Emitir una orden de arresto contra alguien")) 
						controladorDeLaOrdenDeArresto.procesarEntradasParaOrdenarUnArresto(entradaDeTeclado);
				
					else if(eleccion.matches("Guardar la partida actual")) 
						controladorDeLaPartida.procesarEntradasParaGuardarUnaPartida(entradaDeTeclado);
				
					else if(eleccion.matches("Cargar una partida guardada")) {
						boolean seCargoUnaPartida = controladorDeLaPartida.procesarEntradasParaCargarUnaPartida(entradaDeTeclado);
						if (seCargoUnaPartida)
							controladorDelViaje.actualizar();
					}
				}
			
				controladorDelFinalDelJuego.procesarEntradasFinalesDelJugador(entradaDeTeclado);
			}
		} 
		catch (CasoNoIniciadoException excepcion) {
			// Nunca se llega a una situacion en que no se haya iniciado un
			// caso (en condiciones normales de la computadora).
			VistaJuego.graficarMensajeDeError(excepcion);
		}
		
		entradaDeTeclado.close();
	}
}
